﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace CardMonitor.Utils
{
  
        /// <summary>
        /// 读卡器操作类（支持ISO14443A协议）
        /// </summary>
        public class CardReader : IDisposable
        {
            #region 常量定义
            private const byte STX = 0xF2;   // 起始符
            private const byte ETX = 0x03;   // 结束符
            private const byte ACK = 0x06;   // 确认应答
            private const byte NAK = 0x15;   // 否认应答
            private const int ResponseTimeout = 2000; // 响应超时(ms)
            #endregion

            #region 字段/属性
            private readonly SerialPort _serialPort;
            private readonly object _comLock = new object();
            private bool _disposed;

            /// <summary>
            /// 读卡器地址
            /// </summary>
            public byte DeviceAddress { get; set; } = 0x01;

            /// <summary>
            /// 串口连接状态
            /// </summary>
            public bool IsConnected => _serialPort.IsOpen;
            #endregion

            #region 构造函数
            public CardReader(string portName = "COM8", int baudRate = 9600)
            {
                _serialPort = new SerialPort(portName, baudRate)
                {
                    Parity = Parity.None,
                    DataBits = 8,
                    StopBits = StopBits.One,
                    ReadTimeout = ResponseTimeout,
                    WriteTimeout = ResponseTimeout
                };
            }
            #endregion

            #region 基础通信
            /// <summary>
            /// 打开设备连接
            /// </summary>
            public void Connect()
            {
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                    Thread.Sleep(100); // 等待设备初始化
                }
            }

            /// <summary>
            /// 关闭设备连接
            /// </summary>
            public void Disconnect()
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }
            }

            /// <summary>
            /// 发送命令（同步）
            /// </summary>
            public byte[] SendCommand(byte[] command)
            {
                lock (_comLock)
                {
                    // 清空缓冲区
                    _serialPort.DiscardInBuffer();
                    _serialPort.DiscardOutBuffer();

                    // 发送命令
                    _serialPort.Write(command, 0, command.Length);

                    // 读取响应
                    return ReadResponse();
                }
            }

            /// <summary>
            /// 发送命令（异步）
            /// </summary>
            public async Task<byte[]> SendCommandAsync(byte[] command)
            {
                return await Task.Run(() => SendCommand(command));
            }

            private byte[] ReadResponse()
            {
                var startTime = DateTime.Now;
                var buffer = new byte[256];
                var index = 0;

                while ((DateTime.Now - startTime).TotalMilliseconds < ResponseTimeout)
                {
                    if (_serialPort.BytesToRead >= 0)
                    {
                        int bytesRead = _serialPort.Read(buffer, index, buffer.Length - index);
                        index += bytesRead;

                        if (ValidateResponse(buffer, index))
                        {
                            byte[] response = new byte[index];
                            Array.Copy(buffer, response, index);
                            return response;
                        }
                    }
                    Thread.Sleep(10);
                }
                throw new TimeoutException("设备响应超时");
            }
            #endregion

            #region 协议相关方法
            /// <summary>
            /// 寻卡操作（ISO14443A）
            /// </summary>
            public byte[] RequestCard()
            {
                var command = BuildCommand(0x30, new byte[] { 0x26 }); // REQALL
                var response = SendCommand(command);

                if (response[4] == 0x31 && response[5] == 0x00)
                {
                    byte[] cardId = new byte[4];
                    Array.Copy(response, 6, cardId, 0, 4);
                    return cardId;
                }
                throw new InvalidOperationException("寻卡失败");
            }

            /// <summary>
            /// 写卡数据（块写入）
            /// </summary>
            public bool WriteCardData(byte blockNumber, byte[] data)
            {
                if (data.Length != 4)
                    throw new ArgumentException("数据长度必须为4字节");

                var command = BuildCommand(0x32, new[] { blockNumber }, data);
                var response = SendCommand(command);

                return response[4] == 0x33 && response[5] == 0x00;
            }

            /// <summary>
            /// 发卡操作
            /// </summary>
            public async Task<bool> IssueCardAsync()
            {
                try
                {
                    await SendCommandAsync(BuildCommand(0x34)); // 进卡
                    await Task.Delay(500);
                    await SendCommandAsync(BuildCommand(0x35)); // 移卡
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            #endregion

            #region 协议构建
            public byte[] BuildCommand(byte cmd, byte[] parameters = null, byte[] data = null)
            {
                var packet = new System.Collections.Generic.List<byte>
            {
                STX,
                DeviceAddress
            };

                // 长度计算（CMD + PM + DATA + ETX + BCC）
                int dataLength = 1 + (parameters?.Length ?? 0) + (data?.Length ?? 0) + 2;
                packet.Add((byte)(dataLength >> 8));  // LENH
                packet.Add((byte)dataLength);         // LENL

                // 命令部分
                packet.Add(cmd);
                if (parameters != null) packet.AddRange(parameters);
                if (data != null) packet.AddRange(data);
                packet.Add(ETX);

                // BCC校验
                byte bcc = 0;
                foreach (byte b in packet) bcc ^= b;
                packet.Add(bcc);

                return packet.ToArray();
            }

            private bool ValidateResponse(byte[] response, int length)
            {
                if (length < 6) return false;

                // 校验BCC
                byte bcc = 0;
                for (int i = 0; i < length - 1; i++)
                    bcc ^= response[i];

                return response[0] == STX &&
                       response[length - 2] == ETX &&
                       response[length - 1] == bcc;
            }
            #endregion

            #region 释放资源
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }

            protected virtual void Dispose(bool disposing)
            {
                if (!_disposed)
                {
                    if (disposing)
                    {
                        _serialPort?.Close();
                        _serialPort?.Dispose();
                    }
                    _disposed = true;
                }
            }
            #endregion
        }
    
}
